package com.huike.report.service.impl;

import com.huike.clues.mapper.SysDeptMapper;
import com.huike.common.core.domain.entity.SysDept;
import com.huike.report.domain.vo.*;
import com.huike.clues.domain.TbActivity;
import com.huike.clues.domain.TbClue;
import com.huike.clues.mapper.SysDictDataMapper;
import com.huike.clues.mapper.TbActivityMapper;
import com.huike.clues.mapper.TbClueMapper;
import com.huike.common.utils.bean.BeanUtils;
import com.huike.contract.domain.TbContract;
import com.huike.contract.mapper.TbContractMapper;
import com.huike.report.domain.vo.LineChartVo;
import com.huike.report.domain.vo.LineSeriesVo;
import com.huike.report.mapper.ReportMapper;
import com.huike.report.service.ReportService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * @Author: Copyright by jiyuzm & wwq
 * @Date: 2023/07/13/17:10
 * @Description: 报表-统计分析
 */

@Service
@AllArgsConstructor
public class ReportServiceImpl implements ReportService {

    private ReportMapper reportMapper;
    private TbActivityMapper activityMapper;
    private TbClueMapper clueMapper;
    private SysDictDataMapper sysDictDataMapper;
    private TbContractMapper contractMapper;
    private SysDeptMapper deptMapper;

    /**
     * 渠道统计活动明细列表
     * @param activity 传入活动参数
     * @return TableDataInfo«List«渠道统计活动明细数据对象»»
     */
    @Override
    public List<ActivityStatisticsVo> activityStatisticsList(TbActivity activity) {
        activity.setStatus("2");
        List<TbActivity> activities = activityMapper.selectActivityList(activity);
        Map<String, Object> timeMap = activity.getParams();
        List<ActivityStatisticsVo> list = new ArrayList<>();
        for (TbActivity activity2 : activities) {
            ActivityStatisticsVo dto = new ActivityStatisticsVo();
            BeanUtils.copyProperties(activity2, dto);
            TbClue tbClue = new TbClue();
            tbClue.setActivityId(activity2.getId());
            tbClue.setChannel(activity2.getChannel());
            tbClue.setParams(timeMap);
            Map<String, Object> clueCount = clueMapper.countByActivity(tbClue);
            if (clueCount != null) {
                dto.setCluesNum(Integer.parseInt(clueCount.get("total").toString()));
                if (clueCount.get("falseClues") != null) {
                    dto.setFalseCluesNum(Integer.parseInt(clueCount.get("falseClues").toString()));
                }
                if (clueCount.get("toBusiness") != null) {
                    dto.setBusinessNum(Integer.parseInt(clueCount.get("toBusiness").toString()));
                }
            }
            TbContract tbContract = new TbContract();
            tbContract.setChannel(activity2.getChannel());
            tbContract.setActivityId(activity2.getId());
            tbContract.setParams(timeMap);
            Map<String, Object> contractCount = contractMapper.countByActivity(tbContract);
            if (contractCount != null) {
                dto.setCustomersNum(Integer.parseInt(contractCount.get("customersNum").toString()));
                if (contractCount.get("amount") == null) {
                    dto.setAmount(0d);
                } else {
                    dto.setAmount((Double) contractCount.get("amount"));
                }
                if (contractCount.get("cost") == null) {
                    dto.setCost(0d);
                } else {
                    dto.setCost((Double) contractCount.get("cost"));
                }

            }
            list.add(dto);
        }
        return list;
    }


    /**
     * 渠道统计-活动统计
     * @param beginCreateTime /
     * @param endCreateTime   /
     * @return /
     */
    @Override
    public List<Map<String, Object>> activityStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data = contractMapper.activityStatistics(beginCreateTime, endCreateTime);
        for (Map<String, Object> datum : data) {
            Long activityId = (Long) datum.get("activity_id");
            TbActivity tbActivity = activityMapper.getById(activityId);
            if (tbActivity == null) {
                datum.put("activity", "其他");
            } else {
                datum.put("activity", tbActivity.getName());
            }
        }
        return data;

    }

    /**
     * 渠道统计
     * @param beginCreateTime /
     * @param endCreateTime   /
     * @return /
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data = contractMapper.chanelStatistics(beginCreateTime, endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue = (String) datum.get("channel");
            String lable = sysDictDataMapper.selectDictLabel("clues_item", subjectValue);
            datum.put("channel", lable);
        }
        return data;
    }

    /**
     * 销售统计归属渠道明细列表
     * @param beginCreateTime /
     * @param endCreateTime   /
     * @return /
     */
    @Override
    public List<Map<String, Object>> channelStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data = contractMapper.channelStatisticsList(beginCreateTime, endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue = (String) datum.get("channel");
            if (subjectValue != null) {
                String lable = sysDictDataMapper.selectDictLabel("clues_item", subjectValue);
                datum.put("channel", lable);
            }
        }
        return data;

    }


    /**
     * 线索统计新增线索数量报表
     * @param beginCreateTime /
     * @param endCreateTime   /
     * @return /
     */
    @Override
    public LineChartVo cluesStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVo lineChartVo = new LineChartVo();
        try {
            //调用时间方法，获取到连续时间的集合
            List<String> timeList = findDates(beginCreateTime, endCreateTime);
            //把时间集合属性存到结果集对象
            lineChartVo.setxAxis(timeList);
            //创建seriers集合准备存储数据
            List<LineSeriesVo> series = new ArrayList<>();
            //数据库查询时间区间范围内的每日新增数量（string是日期，num是Object）
            List<Map<String, Object>> statistics = clueMapper.cluesStatistics(beginCreateTime, endCreateTime);
            //首先定义一个存name和data数据的对象，name赋值为新增线索数
            LineSeriesVo lineSeriesDTO1 = new LineSeriesVo();
            lineSeriesDTO1.setName("新增线索数");
            //再定义一个存name和data数据的对象，name赋值为线索总数
            LineSeriesVo lineSeriesDTO2 = new LineSeriesVo();
            lineSeriesDTO2.setName("线索总数");
            //定义一个线索总数
            int sum = 0;
            //对日期进行遍历
            for (String s : timeList) {
                Optional optional = statistics.stream().filter(d -> d.get("dd").equals(s)).findFirst();
                if (optional.isPresent()) {
                    Map<String, Object> cuurentData = (Map<String, Object>) optional.get();
                    lineSeriesDTO1.getData().add(cuurentData.get("num"));
                    sum += Integer.parseInt(cuurentData.get("num").toString());
                } else {
                    lineSeriesDTO1.getData().add(0);
                }
                lineSeriesDTO2.getData().add(sum);
            }
            series.add(lineSeriesDTO1);
            series.add(lineSeriesDTO2);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            // e.printStackTrace();
        }
        return lineChartVo;
    }


    /**
     * 线索统计明细列表
     * @param clue /
     * @return /
     */
    @Override
    public List<TbClue> cluesStatisticsList(TbClue clue) {
        return clueMapper.selectTbClueForReport(clue);
    }

    /**
     * 客户统计新增客户数报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public LineChartVo contractStatistics(String beginCreateTime, String endCreateTime) {
        // 创建LineChartVo折线图对象
        LineChartVo lineChartVo = new LineChartVo();
        try {
            // 获取两个日期范围内的所有日期集合
            List<String> dateList= findDates(beginCreateTime,endCreateTime);
            // 封装x轴
            lineChartVo.setxAxis(dateList);
            // 折线图数据
            List<LineSeriesVo> series = new ArrayList<>();
            // 客户统计
            List<Map<String,Object>>  statistics = contractMapper.contractStatistics(beginCreateTime,endCreateTime);
            // 新增客户折线
            LineSeriesVo newContract=new LineSeriesVo();
            newContract.setName("新增客户数");
            // 客户总数折线
            LineSeriesVo allContract=new LineSeriesVo();
            allContract.setName("客户总数");
            int sum =0;
            for (String s : dateList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    newContract.getData().add(cuurentData.get("num"));
                    sum += Integer.parseInt(cuurentData.get("num").toString());
                }else{
                    newContract.getData().add(0);
                }
                allContract.getData().add(sum);
            }
            series.add(newContract);
            series.add(allContract);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return  lineChartVo;
    }

    /**
     * 客户统计明细列表
     *
     * @param tbContract
     * @return
     */
    @Override
    public List<TbContract> contractReportList(TbContract tbContract) {
        return contractMapper.selectTbContractList(tbContract);
    }

    /**
     * 销售统计归属部门明细列表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> deptStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.deptStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= deptMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return data;
    }

    /**
     * 线索统计线索转换率报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public Object getVulnerabilityMap(String beginCreateTime, String endCreateTime) {
        VulnerabilityMapVo vulnerabilityMapVo = new VulnerabilityMapVo();
        vulnerabilityMapVo.setCluesNums(reportMapper.getCluesNums(beginCreateTime, endCreateTime));
        vulnerabilityMapVo.setEffectiveCluesNums(reportMapper.getEffectiveCluesNums(beginCreateTime, endCreateTime));
        vulnerabilityMapVo.setBusinessNums(reportMapper.getBusinessNums(beginCreateTime, endCreateTime));
        vulnerabilityMapVo.setContractNums(reportMapper.getContractNums(beginCreateTime, endCreateTime));
        return vulnerabilityMapVo;
    }

    /**
     * 销售统计归属人报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> ownerShipStatisticsList(String beginCreateTime, String endCreateTime) {
        return  contractMapper.ownerShipStatistics(beginCreateTime,endCreateTime);
    }

    /**
     * 销售统计报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public LineChartVo salesStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVo lineChartVo =new LineChartVo();
        try {
            List<String> timeList= findDates(beginCreateTime,endCreateTime);
            lineChartVo.setxAxis(timeList);
            List<LineSeriesVo> series = new ArrayList<>();
            List<Map<String,Object>>  statistics = contractMapper.salesStatistics(beginCreateTime,endCreateTime);
            LineSeriesVo lineSeriesVo=new LineSeriesVo();
            lineSeriesVo.setName("销售统计");
            int sum=0;
            for (String s : timeList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    lineSeriesVo.getData().add(cuurentData.get("sales"));
                }else{
                    lineSeriesVo.getData().add(0);
                }
            }
            series.add(lineSeriesVo);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return  lineChartVo;
    }

    /**
     * 客户统计学科分布统计报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<PieChartVo> subjectStatistics(String beginCreateTime, String endCreateTime) {
        return reportMapper.subjectStatistics(beginCreateTime,endCreateTime);
    }

    /**
     * @param beginTime
     * @param endTime
     * @return 返回这两个日期范围内的所有日期
     * @throws ParseException
     */
    public static List<String> findDates(String beginTime, String endTime) throws ParseException {
        List<String> dateList = new ArrayList();
        // 时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 把String解析为Date
        Date beginDate = sdf.parse(beginTime);
        Date endDate = sdf.parse(endTime);
        // 把格式化后的开始日期添加到集合
        dateList.add(sdf.format(beginDate));
        // 获取Calendar实例,操作时间日期
        Calendar beginCalendar = Calendar.getInstance();
        Calendar engCalender = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        beginCalendar.setTime(beginDate);
        engCalender.setTime(endDate);
        // 判断日期是否在endDate之后
        while (endDate.after(beginCalendar.getTime())) {
            // 日期+1天
            beginCalendar.add(Calendar.DAY_OF_MONTH, 1);
            // 把格式化后的开始日期添加到集合
            dateList.add(sdf.format(beginCalendar.getTime()));
        }
        return dateList;
    }

}
